/****************************************************************************
 * Elisa 1.0                                                                *
 *--------------------------------------------------------------------------*
 * Author: Vincent Sorin                                                    *
 * Copyright (c) 2004 Laboratoire d'Informatique de Nantes Atlantique       *
 *--------------------------------------------------------------------------*
 * Elisa is distributed WITHOUT ANY WARRANTY. Read the associated           *
 * COPYRIGHT file for more details.                                         *
 *--------------------------------------------------------------------------*
 * elisa_hull_reduction.h                                                   *
 ****************************************************************************/

/**
 * @file elisa_hull_reduction.h
 * @brief Implementation of hull-consistency.
 */


#ifndef _ELISA_HULL_REDUCTION_H
#define _ELISA_HULL_REDUCTION_H

#include "elisa_defs.h"
#include "elisa_reduction.h"

#include "elisa_observer.h"

#include "elisa_real_constraint.h"
#include "elisa_interval_test.h"
#include "elisa_interval_form.h"

#ifdef ELISA_PROFILE
#include "elisa_time.h"
#endif

NAMESPACE_ELISA

/**
 * @ingroup Reduction
 * @class HullReduction
 * @brief Projection operator implementing hull-consistency
 */
class HullReduction : public Reduction
{
public:
	/**
 	 * Constructor
 	 * @param c the constraint to reduce
 	 * @param v the var that the domain must be reduced
 	 * @param cons the factory for IntrevalForm
 	 */
	HullReduction(RealConstraint *c,
	              IntervalFormFactory *cons)
    : m_constr(c),
	  m_testConstr(new RealConstraintRelation(c, cons))
	{
		Reduction::post(c);

		// Listeners for propagation
		VarImplSet::iterator it;
		for (it = m_constr->beginVar(); it != m_constr->endVar(); ++it) {
			(*it)->dependsOn(this, DomainReduction);
		}
	}

	/**
 	 * Destructor
 	 */
	~HullReduction ()
	{
		delete m_testConstr;
	}

	/// Base class's virtual methods
	//@{
	double priority() const
	{
		return 50.0;
	}

	bool reductionAlgorithm();
	//@}

#ifdef ELISA_PROFILE
	/**
 	 * Accumulates the time spent in the reduce operation.
 	 * Only available in profiling mode.
 	 */
	static Clock ClockBox;

	/**
 	 * Counts the number of calls of the reduce operation
 	 * Only available in profiling mode.
 	 */
	static long NumCall;
#endif // ELISA_PROFILE


	string getReductionName() const
	{
		return "Hull";
	}

	void print(std::ostream & os, std::string indent, VecConstraints *v) const
	{
		os << "HullReduction [";
		printConstraints(os, "", v);
		os << "]";
	}

private:
	RealConstraint *m_constr;               // real constraint
	RealConstraintRelation *m_testConstr;	// interval constraint test

	/// Copy protection
	HullReduction & operator=(const HullReduction & o) {}
	HullReduction(const HullReduction & o) : Reduction(o) {}
};

END_NAMESPACE_ELISA

#endif //ELISA_HULL_REDUCTION_H
